﻿/**
 * Author(s): xuming.Wong <xuming.Wong@gmail.com>
 */

using System;
using System.Collections.Generic;

namespace Gk3dEngine
{
    public class GameObjectManager
    {
        private static GameObjectManager _instance;
        protected GameObjectManager()
        {
        }

        public static GameObjectManager getSingleton()
        {
            if (_instance == null)
            {
                _instance = new GameObjectManager();
            }

            return _instance;
        }

        private Dictionary<int, GameObject> _objects = new Dictionary<int, GameObject>();
        private Dictionary<int, Component> _components = new Dictionary<int, Component>();
        private GameObject _root;

        public GameObject getObject(int id)
        {
            if (_objects.ContainsKey(id))
            {
                GameObject result = _objects[id];
                return result;
            }
            return null;
        }

        public Component getComponent(int id)
        {
            if (_components.ContainsKey(id))
            {
                Component result = _components[id];
                return result;
            }
            return null;
        }

        public void addComponent(GameObject gameObject, Component component)
        {
            if (gameObject != null)
            {
                gameObject.addComponent(component);
            }
        }

        internal GameObject createGameObject(int id, bool isRoot)
        {
            GameObject obj = getObject(id);
            if (obj == null)
            {
                obj = new GameObject(id);
                _objects.Add(id, obj);

            }
            if (isRoot)
            {
                _root = obj;
            }
            return obj;
        }

        public bool parentGameObject(int parentId, int childId)
        {
            return false;
        }

        //only called by inner
        internal void createComponent(int id, int type)
        {
            Component component = getComponent(id);

            if (component == null)
            {
                switch (type)
                {
                    case 0://COMPONENT_TRANSFORM
                        component = new TransformComponent(id);
                        _components.Add(id, component);
                        break;
                    case 1://COMPONENT_LIGHT
                        break;
                    case 2://COMPONENT_MESH
                        break;
                    case 3://COMPONENT_SCRIPT
                        break;
                    default:
                        break;
                }
            }
        }

        internal void createScriptComponent(int id, String className)
        {
            Component component = getComponent(id);

            if (component != null)
            {
                return;
            }

            Type classType = Type.GetType(className);
            if (classType != null)
            {
                ScriptComponent script = (ScriptComponent)Activator.CreateInstance(classType);
                script.setId(id);
                _components.Add(id, script);
            }
        }

        //only called by inner
        internal void attachComponent(int objectId, int componentId)
        {
            GameObject gameObject = getObject(objectId);
            Component component = getComponent(componentId);
            if (gameObject != null && component != null)
            {
                component.attach(gameObject);
            }
        }

        internal void addChildGameObject(int parentId, int childId)
        {
            GameObject parent = getObject(parentId);
            GameObject child = getObject(childId);
            if (parent != null && child != null)
            {
                parent.addChild(child);
            }
        }


        internal void update(uint deltaT)
        {
            if (_root != null)
            {
                _root.update(deltaT);
            }
        }

        GameObject createMesh(string name, string meshName)
        {
            GameObject obj = new GameObject();
            MeshComponent meshComponent = new MeshComponent();
            meshComponent.attach(obj);
            return obj;
        }
    }
}
